package com.bestcem.xm.deliver.service.impl;

import cn.hutool.json.JSONUtil;
import com.bestcem.xm.deliver.convert.grpc.DeliverGrpcConvertMapper;
import com.bestcem.xm.deliver.grpc.client.UserGrpcClient;
import com.bestcem.xm.deliver.grpc.client.dto.SmtpDto;
import com.bestcem.xm.deliver.service.MailService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Objects;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * 发送邮件实现类
 *
 * @author panyun <yun.pan@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/11 10:56
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MailServiceImpl implements MailService {

    /**
     * 默认邮箱，配置文件中的spring.mail
     */
    private @NonNull JavaMailSender springDefaultMailSender;

    private @NonNull UserGrpcClient userGrpcClient;

    private @NonNull DeliverGrpcConvertMapper deliverGrpcConvertMapper;

    /**
     * 通用发送邮件
     *
     * @param receiveUsers 收件人邮箱列表
     * @param ccUsers      抄送人邮箱列表
     * @param subject      主题
     * @param content      内容
     * @param smtpId       发件箱
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/19 14:42
     */
    @Override
    public void sendEmail(@Nonnull Collection<String> receiveUsers, @Nullable Collection<String> ccUsers,
                          @Nonnull String subject, @Nonnull String content, String smtpId, SmtpDto smtp) {
        if (log.isInfoEnabled()) {
            log.info("[Deliver] Global sendEmail 接收人:{};抄送人:{};主题:{};\n 内容:{};邮箱id:{};\n邮箱smtp:{}", receiveUsers, ccUsers, subject, content, smtpId, JSONUtil.toJsonStr(smtp));
        }
        if (!org.springframework.util.StringUtils.hasText(smtpId) && smtp == null) {
            log.error("[Deliver]  sendEmail smtpId smtp 必须要有一个");
            return;
        }
        if (!CollectionUtils.isEmpty(receiveUsers)) {
            // 去掉列表中的null
            receiveUsers = receiveUsers.stream().filter(Objects::nonNull).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(receiveUsers)) {
                log.error("[Deliver] sendEmail 收件人不能为空");
            }
        }
        if (!CollectionUtils.isEmpty(ccUsers)) {
            // 去掉列表中的null
            ccUsers = ccUsers.stream().filter(Objects::nonNull).collect(Collectors.toList());
        }

        JavaMailSenderImpl mailSender;
        if (Objects.nonNull(smtp)) {
            mailSender = getMailSender(smtp);
        } else {
            SmtpDto userSmtp = deliverGrpcConvertMapper.toSmtpDto(userGrpcClient.getUserSmtpById(smtpId));
            if (Objects.isNull(userSmtp)) {
                log.error("没有找到对应的[{}]用户邮箱,临时使用配置邮箱", smtpId);
                mailSender = (JavaMailSenderImpl) springDefaultMailSender;
            } else {
                mailSender = getMailSender(userSmtp);
            }
        }
        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, String.valueOf(StandardCharsets.UTF_8));
            //收件人
            helper.setTo(receiveUsers.toArray(new String[0]));
            if (!CollectionUtils.isEmpty(ccUsers)) {
                //抄送人
                helper.setCc(ccUsers.toArray(new String[0]));
            }
            //主题
            helper.setSubject(subject);
            //内容
            helper.setText(content, true);
            helper.setFrom(Objects.requireNonNull(mailSender.getUsername()));
            mailSender.send(message);
        } catch (Exception e) {
            log.error("[Deliver]  sendEmail Exception");
            throw new RuntimeException(e);
        }
    }

    private JavaMailSenderImpl getMailSender(SmtpDto smtp) {
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(smtp.getHost(), Integer.parseInt(smtp.getPort())), 1000);
        } catch (IOException e) {
            log.error("邮箱域名:{},端口:{} 无效 ;", smtp.getHost(), smtp.getPort());
        }

        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setProtocol("smtp");
        sender.setHost(smtp.getHost().trim());
        sender.setUsername(smtp.getAccount());
        sender.setPassword(smtp.getPassword());
        sender.setDefaultEncoding("UTF-8");
        Properties properties = new Properties();
        // 设置超时时间
        properties.setProperty("mail.smtp.timeout", "5000");
        // 如果是ssl的话,需要设置以下属性
        if (Boolean.TRUE.equals(smtp.isSSL())) {
            properties.setProperty("mail.smtp.auth", "true");
            properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            properties.setProperty("mail.smtp.socketFactory.port", String.valueOf(smtp.getPort()));
        }
        sender.setJavaMailProperties(properties);
        return sender;
    }
}
